----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    18:59:16 04/19/2012 
-- Design Name: 
-- Module Name:    RSP_BlockRam - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.faw_types.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity RSP_BlockRam is
    Port ( clk_rspbr : in  STD_LOGIC;
           camera_pixel_rspbr : in  STD_LOGIC_VECTOR (7 downto 0);
			  i_rspbr : in COUNTER_ROWS;
			  j_rspbr : in COUNTER_COLUMNS;
			  pixel_valid_rspbr : in std_logic;
			  line_valid_rspbr : in std_logic;
			  frame_valid_rspbr : in std_logic;
			  ena_rspbr : out BR_ENABLE_BUS;
			  enb_rspbr : out BR_ENABLE_BUS;
			   wea_rspbr : out BR_WEA_BUS;
				addra_rspbr : out RSP_BR_ADDRESS_BUS;
				addrb_rspbr : out RSP_BR_ADDRESS_BUS;
				dina_rspbr : out std_logic_vector(7 downto 0);
           data_out_rspbr : out RSPSR_SR_DATA_BUS);

end RSP_BlockRam;

architecture Behavioral of RSP_BlockRam is

component BR_CAMPIONAMENTO_REFERENCE is
		port(
			clka : IN STD_LOGIC;
			ena : IN STD_LOGIC;
			wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
			addra : IN STD_LOGIC_VECTOR(N_BIT_BR_SAMPLED-1 DOWNTO 0);
			dina : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
			clkb : IN STD_LOGIC;
			enb : IN STD_LOGIC;
			addrb : IN STD_LOGIC_VECTOR(N_BIT_BR_SAMPLED-1 DOWNTO 0);
			doutb : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
		);
end component;

	
	signal ENA_INTERNAL: BR_ENABLE_BUS;
	signal WEA_INTERNAL: BR_WEA_BUS;
	signal ADDRA_INTERNAL: RSP_BR_ADDRESS_BUS;
	signal ADDRB_INTERNAL: RSP_BR_ADDRESS_BUS;
	signal ENB_INTERNAL: BR_ENABLE_BUS;
	
	
	constant ADDR_MODULE : integer :=W/P;

begin

	
	BlockRamRSP : for i in 0 to RSPSRC_SR_REGISTERS-1 generate
		comp: BR_CAMPIONAMENTO_REFERENCE
		port map(
				clka => clk_rspbr,
				ena => ENA_INTERNAL(i),
				wea => WEA_INTERNAL(i),
				addra => ADDRA_INTERNAL(i),
				dina => camera_pixel_rspbr,
				clkb => clk_rspbr,
				enb => ENB_INTERNAL(i),
				addrb => ADDRB_INTERNAL(i),
				doutb => data_out_rspbr(i)
		);
	end generate BlockRamRSP;

	processo:process(clk_rspbr)
		 
	variable ENA_VAR: BR_ENABLE_BUS;
	variable WEA_VAR:  BR_WEA_BUS;
	variable ADDRA_VAR: RSP_BR_ADDRESS_BUS;
	variable ADDRB_VAR: RSP_BR_ADDRESS_BUS;
	variable ENB_VAR: BR_ENABLE_BUS;
	variable INTERNALCOUNTER_WRITER_CC: integer:=0;
	variable INTERNALCOUNTER_READER_CC: integer:=0;
	
		begin
			if (clk_rspbr'event and clk_rspbr='1') then
				if(pixel_valid_rspbr='1' and line_valid_rspbr='1' and frame_valid_rspbr='1')then
					if((i_rspbr mod P=0) and (j_rspbr mod P = 0) ) then 
					--scrittura sulla block ram relativa alla riga di campionamento
						ENA_VAR( (i_rspbr/P) mod RSPSRC_SR_REGISTERS ):='1';
						WEA_VAR( (i_rspbr/P) mod RSPSRC_SR_REGISTERS ):="1";
						ADDRA_VAR((i_rspbr/p) mod RSPSRC_SR_REGISTERS) :=std_logic_vector(to_unsigned( (INTERNALCOUNTER_WRITER_CC) mod (ADDR_MODULE) ,N_BIT_BR_SAMPLED)); -- sottraggo uno perch il primo pixel  di coordinate (1,1)
			
					-- lettura dalle block ram eccetto quella su cui si ha scritto. 
						for k in 0 to RSPSRC_SR_REGISTERS-1 loop
							if (not(k = ((i_rspbr/p) mod RSPSRC_SR_REGISTERS))) then
								ENB_VAR(k):='1';
								ADDRB_VAR(k):=std_logic_vector(to_unsigned( (INTERNALCOUNTER_CC) mod (ADDR_MODULE) ,N_BIT_BR_SAMPLED));		
							else
								ENB_VAR(k):='0';
							end if;		
						end loop;
					--incremento indirizzo
						INTERNALCOUNTER_WRITER_CC:=INTERNALCOUNTER_WRITER_CC+1;
					else
					-- lettura da tutte le block ram all'indirizzo INTERNALCOUNTER_CC
						for k in 0 to RSPSRC_SR_REGISTERS-1 loop
							ENB_VAR(k):='1';
							ADDRB_VAR(k):=std_logic_vector(to_unsigned( (INTERNALCOUNTER_CC) mod (ADDR_MODULE) ,N_BIT_BR_SAMPLED));		
						
							ENA_VAR(k):='0';
							WEA_VAR(k):="0";
						end loop;
						--aggiorno indirizzo quando deve essere fornito un nuovo punto di campionamento agli SR
						if (j_rspbr mod P = 0) then
							INTERNALCOUNTER_CC:=INTERNALCOUNTER_CC+1;
						end if;
					end if;
				end if;
			end if;
			
		
		ENA_INTERNAL<=ENA_VAR;
		WEA_INTERNAL<=WEA_VAR;
	   ADDRA_INTERNAL<=ADDRA_VAR;
	   ADDRB_INTERNAL<=ADDRB_VAR;
	   ENB_INTERNAL<=ENB_VAR;
		
-- per testing
		ena_rspbr<=ENA_VAR;
		wea_rspbr<=WEA_VAR;
		addra_rspbr<=ADDRA_VAR; 
		dina_rspbr<=camera_pixel_rspbr;
		enb_rspbr<=ENB_VAR;
		addrb_rspbr<=ADDRB_VAR;
		end process;

end Behavioral;

